wvd-sh/Update an existing WVD host pool/Scripts/RemoveScript.ps1 (289 lines of code) (raw):

param( [Parameter(mandatory = $true)] [string]$RDBrokerURL, [Parameter(mandatory = $true)] [string]$TenantName, [Parameter(mandatory = $true)] [string]$HostPoolName, [Parameter(mandatory = $true)] [string]$TenantAdminUPN, [Parameter(mandatory = $true)] [string]$TenantAdminPassword, [Parameter(mandatory = $true)] [string]$SubscriptionId, [Parameter(mandatory = $false)] [string]$FileURI, [Parameter(mandatory = $false)] [double]$Hours, [Parameter(mandatory = $false)] [int]$userLogoffDelayInMinutes, [Parameter(mandatory = $false)] [string]$userNotificationMessege, [Parameter(mandatory = $false)] [string]$messageTitle, [Parameter(mandatory = $true)] [string]$deleteordeallocateVMs, [Parameter(mandatory = $true)] [string]$DomainName, [Parameter(mandatory = $true)] [string]$localAdminUsername, [Parameter(mandatory = $true)] [string]$localAdminPassword ) Function Write-Log { [CmdletBinding()] param ( [Parameter(Mandatory = $false)] [string]$Message, [Parameter(Mandatory = $false)] [string]$Error ) try { $DateTime = Get-Date -Format ‘MM-dd-yy HH:mm:ss’ $Invocation = "$($MyInvocation.MyCommand.Source):$($MyInvocation.ScriptLineNumber)" if ($Message) { Add-Content -Value "$DateTime - $Invocation - $Message" -Path "$([environment]::GetEnvironmentVariable('TEMP', 'Machine'))\ScriptLog.log" } else { Add-Content -Value "$DateTime - $Invocation - $Error" -Path "$([environment]::GetEnvironmentVariable('TEMP', 'Machine'))\ScriptLog.log" } } catch { Write-Error $_.Exception.Message } } Invoke-WebRequest -Uri $fileURI -OutFile "C:\DeployAgent.zip" Write-Log -Message "Downloaded DeployAgent.zip into this location C:\" #Creating a folder inside rdsh vm for extracting deployagent zip file New-Item -Path "C:\DeployAgent" -ItemType directory -Force -ErrorAction SilentlyContinue Write-Log -Message "Created a new folder 'DeployAgent' inside VM" Expand-Archive "C:\DeployAgent.zip" -DestinationPath "C:\DeployAgent" -ErrorAction SilentlyContinue Write-Log -Message "Extracted the 'Deployagent.zip' file into 'C:\Deployagent' folder inside VM" Set-Location "C:\DeployAgent" Write-Log -Message "Setting up the location of Deployagent folder" do{ Write-Output "checking nuget package exists or not" if (!(Get-PackageProvider -Name NuGet -ErrorAction SilentlyContinue -ListAvailable)) { Write-Output "installing nuget package inside vm: $env:COMPUTERNAME" Install-PackageProvider -Name nuget -Force } $LoadModule=Get-Module -ListAvailable "Azure*" if(!$LoadModule){ Write-Output "installing azureModule inside vm: $env:COMPUTERNAME" Install-Module AzureRm -AllowClobber -Force } } until($LoadModule) Import-Module ".\PowershellModules\Microsoft.RDInfra.RDPowershell.dll" #AzureLogin Credentials $Securepass=ConvertTo-SecureString -String $TenantAdminPassword -AsPlainText -Force $Credentials=New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList($TenantAdminUPN, $Securepass) #Domain Credentials $AdminSecurepass = ConvertTo-SecureString -String $localAdminPassword -AsPlainText -Force $AdminCredentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList ($localAdminUsername, $AdminSecurepass) #Setting RDS Context $authentication=Set-RdsContext -DeploymentUrl $RDBrokerURL -Credential $Credentials $obj = $authentication | Out-String if ($authentication) { Write-Log -Message "Imported RDMI PowerShell modules successfully done" Write-Log -Message "RDMI Authentication successfully done. Result: ` $obj" } else { Write-Log -Error "RDMI Authentication Failed, Error: ` $obj" } $allshs=Get-RdsSessionHost -TenantName $tenantname -HostPoolName $HostPoolName $allshslog=$allshs.name | Out-String Write-Log -Message "All Session Host servers in $HostPoolName :` $allshslog" $shsNames=0 $shsNames=@() $rdsUserSessions=Get-RdsUserSession -TenantName $TenantName -HostPoolName $HostPoolName if($rdsUserSessions){ foreach($rdsUserSession in $rdsUserSessions){ $sessionId=$rdsUserSession.SessionId $shName=$rdsUserSession.SessionHostName $username=$rdsUserSession.UserPrincipalName | Out-String $shsNames+=$shName #Send-RdsUserSessionMessage -TenantName $TenantName -HostPoolName $HostPoolName -SessionHostName $shName -SessionId $sessionId -MessageTitle $messageTitle -MessageBody $userNotificationMessage -NoConfirm:$false #Write-log -message "Sent a rdsusersesionmessage to $username and sessionid was $sessionId" } } else { $shName=$allshs.SessionHostName Write-Log -Message "Sessions not present in $shName session host vm" $shsNames+=$shName } $allShsNames=$shsNames | select -Unique Write-Log -Message "Collected old sessionhosts of Hostpool $HostPoolName : ` $allShsNames" #Get Domaincontroller VMname $DName=Get-ADDomainController -Discover -DomainName $DomainName $DControllerVM=$DName.Name $ZoneName=$DName.Forest #Import-Module AzureRM.Resources #Import-Module Azurerm $AzSecurepass=ConvertTo-SecureString -String $TenantAdminPassword -AsPlainText -Force $AzCredentials=New-Object System.Management.Automation.PSCredential($TenantAdminUPN, $AzSecurepass) $loginResult=Login-AzureRmAccount -SubscriptionId $SubscriptionId -Credential $AzCredentials if ($loginResult.Context.Subscription.Id -eq $SubscriptionId) { $success=$true Write-Log -Message "Successfully logged into AzureRM" } else { Write-Log -Error "Subscription Id $SubscriptionId not in context" } $convertSeconds=$userLogoffDelayInMinutes * 60 Start-Sleep -Seconds $convertSeconds foreach($sh in $allShsNames){ # setting rdsh vm in drain mode $shsDrain=Set-RdsSessionHost -TenantName $tenantname -HostPoolName $HostPoolName -Name $sh -AllowNewSession $false $shsDrainlog=$shsDrain | Out-String Write-Log -Message "Sesssion host server in drain mode : ` $shsDrainlog" Remove-RdsSessionHost -TenantName $tenantname -HostPoolName $HostPoolName -Name $sh -Force $true Write-Log -Message "Successfully $sh removed from hostpool" $VMName=$sh.Split(".")[0] if($deleteordeallocateVMs -eq "Delete"){ # Remove the VM's and then remove the datadisks, osdisk, NICs Get-AzureRmVM | Where-Object {$_.name -eq $VMName} | foreach { $a=$_ $DataDisks = @($_.StorageProfile.DataDisks.Name) $OSDisk = @($_.StorageProfile.OSDisk.Name) Write-Log -Message "Removing $VMName VM and associated resources from Azure" #Write-Warning -Message "Removing VM: $($_.Name)" $_ | Remove-AzureRmVM -Force -Confirm:$false Write-Log -Message "Successfully removed VM from Azure" $_.NetworkProfile.NetworkInterfaces | ForEach-Object { $NICName = Split-Path -Path $_.ID -leaf #Write-Warning -Message "Removing NIC: $NICName" #Get-AzureRmNetworkInterface -ResourceGroupName $ResourceGroup -Name $NICName | Remove-AzureRmNetworkInterface -Force Get-AzureRmNetworkInterface | Where-Object {$_.Name -eq $NICName} | Remove-AzureRmNetworkInterface -Force } Write-Log -Message "Successfully removed $VMName vm NIC" # Support to remove managed disks if($a.StorageProfile.OsDisk.ManagedDisk ) { ($DataDisks + $OSDisk) | ForEach-Object { #Write-Warning -Message "Removing Disk: $_" #Get-AzureRmDisk -ResourceGroupName $ResourceGroup -DiskName $_ | Remove-AzureRmDisk -Force } } # Support to remove unmanaged disks (from Storage Account Blob) else { # This assumes that OSDISK and DATADisks are on the same blob storage account # Modify the function if that is not the case. $saname = ($a.StorageProfile.OsDisk.Vhd.Uri -split '\.' | Select -First 1) -split '//' | Select -Last 1 $sa = Get-AzureRmStorageAccount | Where-Object {$_.StorageAccountName -eq $saname} # Remove DATA disks $a.StorageProfile.DataDisks | foreach { $disk = $_.Vhd.Uri | Split-Path -Leaf Get-AzureStorageContainer -Name vhds -Context $Sa.Context | Get-AzureStorageBlob -Blob $disk | Remove-AzureStorageBlob Write-Log -Message "Removed DataDisk $disk successfully" } # Remove OSDisk disk $disk = $a.StorageProfile.OsDisk.Vhd.Uri | Split-Path -Leaf Get-AzureStorageContainer -Name vhds -Context $Sa.Context | Get-AzureStorageBlob -Blob $disk | Remove-AzureStorageBlob Write-Log -Message "Removed OSDisk $disk successfully" # Remove Boot Diagnostic $diagVMName=0 $diag=$_.Name.ToLower() $diagVMName=$diag -replace '[\-]', '' $dCount=$diagVMName.Length if($dCount -cgt 9){ $digsplt=$diagVMName.substring(0,9) $diagVMName=$digsplt } $diagContainerName = ('bootdiagnostics-{0}-{1}' -f $diagVMName, $_.VmId) Set-AzureRmCurrentStorageAccount -Context $sa.Context Remove-AzureStorageContainer -Name $diagContainerName -Force Write-Log -Message "Successfully removed boot diagnostic" } #$avSet=Get-AzureRmVM | Where-Object {$_.Name -eq $VMName} | Remove-AzureRmAvailabilitySet -Force $avset=Get-AzureRmAvailabilitySet -ResourceGroupName $a.ResourceGroupName if($avset.VirtualMachinesReferences.id -eq $null){ $removeavset=Get-AzureRmAvailabilitySet -ResourceGroupName $a.ResourceGroupName -ErrorAction SilentlyContinue | Remove-AzureRmAvailabilitySet -Force Write-Log -Message "Successfully removed availabilityset" } $checkResources=Get-AzureRmResource -ResourceGroupName $a.ResourceGroupName if(!$checkResources){ $removeRg=Remove-AzureRmResourceGroup -Name $a.ResourceGroupName -Force Write-Log -Message "Successfully removed ResourceGroup" } } #Removing VM from domain controller and DNS Record $result=Invoke-Command -ComputerName $DControllerVM -Credential $AdminCredentials -ScriptBlock{ Param($ZoneName,$VMName) Get-ADComputer -Identity $VMName | Remove-ADObject -Recursive -confirm:$false Remove-DnsServerResourceRecord -ZoneName $ZoneName -RRType "A" -Name $VMName -Force -Confirm:$false } -ArgumentList($ZoneName,$VMName) -ErrorAction SilentlyContinue if($result){ Write-Log -Message "Successfully removed $VMName from domaincontroller" Write-Log -Message "successfully removed dns record of $VMName" } } else{ $vmProvisioning=Get-AzureRmVM | Where-Object {$_.Name -eq $VMName} | Stop-AzureRmVM -Force if($vmProvisioning.Status -eq "Succeeded"){ write-log -Message "VM has been stopped: $VMName" } else { write-log -Error "$VMName VM cannot be stopped" } } } #Adding new vm instance to existing hostpool $CheckRegistery = Get-ItemProperty -Path "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\RDInfraAgent" -ErrorAction SilentlyContinue Write-Log -Message "Checking whether VM is Registered with RDInfraAgent" if ($CheckRegistery){ Write-Log -Message "VM was already registered with RDInfraAgent, script execution was stopped" } else { Write-Log -Message "VM was not registered with RDInfraAgent, script is executing now" } if (!$CheckRegistery){ $HPName = Get-RdsHostPool -TenantName $TenantName -Name $HostPoolName -ErrorAction SilentlyContinue Write-Log -Message "Checking Hostpool exists inside the Tenant" if ($HPName) { Write-log -Message "Hostpool exists inside tenant: $TenantName" Write-Log -Message "Checking Hostpool UseResversconnect is true or false" if ($HPName.UseReverseConnect -eq $False) { Write-Log -Message "Usereverseconnect is false, it will be changed to true" Set-RdsHostPool -TenantName $TenantName -Name $HostPoolName -UseReverseConnect $true } else{ Write-Log -Message "Hostpool Usereverseconnect already enabled as true" } $SessionHostName = (Get-WmiObject win32_computersystem).DNSHostName + "." + (Get-WmiObject win32_computersystem).Domain $Registered = Export-RdsRegistrationInfo -TenantName $TenantName -HostPoolName $HostPoolName $reglog = $registered | Out-String Write-Log -Message "Exported Rds RegisterationInfo into variable 'Registered': $reglog" $systemdate = (GET-DATE) $Tokenexpiredate = $Registered.ExpirationUtc $difference = $Tokenexpiredate - $systemdate write-log -Message "Calculating date and time of expiration with system date and time" if ($difference -lt 0 -or $Registered -eq 'null') { write-log -Message "Registerationinfo has expired, Creating new registeration info with hours $Hours" $Registered = New-RdsRegistrationInfo -TenantName $TenantName -HostPoolName $HostPoolName -ExpirationHours $Hours } else { $reglogexpired = $Tokenexpiredate | Out-String -Stream Write-Log -Message "Registerationinfo is not expired, expiring in $reglogexpired" } $DAgentInstall = .\DeployAgent.ps1 -ComputerName $SessionHostName -AgentBootServiceInstaller ".\RDAgentBootLoaderInstall\Microsoft.RDInfra.RDAgentBootLoader.Installer-x64.msi" -AgentInstaller ".\RDInfraAgentInstall\Microsoft.RDInfra.RDAgent.Installer-x64.msi" -SxSStackInstaller ".\RDInfraSxSStackInstall\Microsoft.RDInfra.StackSxS.Installer-x64.msi" -AdminCredentials $AdminCredentials -TenantName $TenantName -PoolName $HostPoolName -RegistrationToken $Registered.Token -StartAgent $true Write-Log -Message "DeployAgent Script was successfully executed and RDAgentBootloader,RDAgent,StackSxS installed inside VM for existing hostpool: $HostPoolName ` $DAgentInstall" $addRdsh = Set-RdsSessionHost -TenantName $TenantName -HostPoolName $HostPoolName -Name $SessionHostName -AllowNewSession $true $rdshName = $addRdsh.name | Out-String -Stream $poolName = $addRdsh.hostpoolname | Out-String -Stream Write-Log -Message "Successfully added $rdshName VM to $poolName" } }